#include <QCoreApplication>
#include <QFile>

#include "CorePlugin.h"

CorePlugin::CorePlugin(QObject* parent, QString name) : QObject(parent) {
	setObjectName(name);
}

CorePlugin::~CorePlugin() {
}

void CorePlugin::LoadData() {
	//очищаем массив плагинов
	libs.clear();

	//запрашиваем список параметров в секции
	QStringList list;
	emit GetParamList("core.ini", "plugins", list);

	for(int i=0; i<list.count(); i++) {
		QString name;
		emit GetValue("core.ini", "plugins", list[i], name);
		LoadPlugin(name);
	}

	//сигнал загрузки всех плагинов
	emit AllPluginsLoaded();
}

void CorePlugin::LoadPlugin(const QString& name, int& res) {
	//проверяем имя плагина на пустоту
	if (name.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CorePlugin::LoadPlugin", QStringList());
		return;
	}

	//проверяем что плагин уже загружен
	if (libs.find(name) == libs.end()) {
		res=2;
		emit SetCurrentError(res, "CorePlugin::LoadPlugin", QStringList() << name);
		return;
	}

	//типы для обращения к функциям библиотеки
	//init_plugin
	typedef void (*Loadlib) (QObject *);
	//info_plugin
	typedef QString (*LoadInfo) ();

	QString pth = qApp->applicationDirPath();
		if (pth.right(1) != "/") { pth += "/"; }
	pth = pth + "plugins/" + name;

	//загружаем библиотеку
	QLibrary* lib = new QLibrary(pth);
	if (!lib->load()) {
		res=3;
		emit SetCurrentError(res, "CorePlugin::LoadPlugin", QStringList() << name);
		return;
	}
	//ищем описание плагина
	QString info = "";
	LoadInfo LoadInfo_ =  (LoadInfo) lib->resolve("info_plugin");
	if (LoadInfo_ != 0) {
		info = LoadInfo_();
	}

	//ищем фушкцию инициализации плагина
	Loadlib Loadlib_ =  (Loadlib) lib->resolve("init_plugin");
	if (Loadlib_ == 0) {
		res=4;
		emit SetCurrentError(res, "CorePlugin::LoadPlugin", QStringList() << name);
		return;
	}

	//инициализируем плагин
	Loadlib_(parent());

	//сохраняем в массив
	LIBDATA ld;
	 ld.info = info;
	 ld.library = lib;
	libs[name] = ld;

	//сигнал загрузки плагина
	emit PluginLoaded(name);

	res=0;
	emit SetCurrentError(res, "CorePlugin::LoadPlugin", QStringList() << name);
}

void CorePlugin::LoadPlugin(const QString& name, bool& res) {
	int r;
	LoadPlugin(name, r);
	res = (r <= 0);
}

void CorePlugin::LoadPlugin(const QString& name) {
	int r;
	LoadPlugin(name, r);
}

void CorePlugin::UnloadPlugin(const QString& name, int& res) {
	//проверяем имя плагина на пустоту
	if (name.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CorePlugin::UnloadPlugin", QStringList());
		return;
	}

	//проверяем что плагин загружен
	if (libs.find(name) == libs.end()) {
		res=-1;
		emit SetCurrentError(res, "CorePlugin::UnloadPlugin", QStringList() << name);
		return;
	}

	//пытаемся выгрузить плагин
	if (!libs[name].library->unload()) {
		res=2;
		emit SetCurrentError(res, "CorePlugin::UnloadPlugin", QStringList() << name);
		return;
	}

	//сигнал выгрузки плагина
	emit PluginUnloaded(name);

	res=0;
	emit SetCurrentError(res, "CorePlugin::UnloadPlugin", QStringList() << name);
}

void CorePlugin::UnloadPlugin(const QString& name, bool& res) {
	int r;
	UnloadPlugin(name, r);
	res = (r <= 0);
}

void CorePlugin::UnloadPlugin(const QString& name) {
	int r;
	UnloadPlugin(name, r);
}

void CorePlugin::UnloadAllPlugins(int& res) {
	//перебираем все загруженные плагины
	LIBS::iterator it;
	for (it = libs.begin(); it != libs.end(); ++it) {
		UnloadPlugin(it->first);
	}

	//сигнал выгрузки всех плагинов
	emit AllPluginsUnloaded();

	res=0;
	emit SetCurrentError(res, "CorePlugin::UnloadAllPlugins", QStringList());
}

void CorePlugin::UnloadAllPlugins(bool& res) {
	int r;
	UnloadAllPlugins(r);
	res = (r <= 0);
}

void CorePlugin::UnloadAllPlugins() {
	int r;
	UnloadAllPlugins(r);
}

void CorePlugin::PluginList(QStringList& list) {
	//очищаем список
	list.clear();

	//перебираем все загруженные плагины
	LIBS::iterator it;
	for (it = libs.begin(); it != libs.end(); ++it) {
		list << it->first;
	}

	emit SetCurrentError(0, "CorePlugin::PluginList", QStringList());
}

void CorePlugin::PluginInfo(const QString& name, QString& info, int& res) {
	//проверяем имя плагина на пустоту
	if (name.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CorePlugin::PluginInfo", QStringList());
		return;
	}

	//проверяем что плагин загружен
	if (libs.find(name) == libs.end()) {
		res=2;
		emit SetCurrentError(res, "CorePlugin::PluginInfo", QStringList() << name);
		return;
	}

	//запрашиваем инфо
	info = libs[name].info;

	res=0;
	emit SetCurrentError(res, "CorePlugin::PluginInfo", QStringList() << name);
}

void CorePlugin::PluginInfo(const QString& name, QString& info, bool& res) {
	int r;
	PluginInfo(name, info, r);
	res = (r <= 0);
}

void CorePlugin::PluginInfo(const QString& name, QString& info) {
	int r;
	PluginInfo(name, info, r);
}

void CorePlugin::AddPlugin(const QString& name, int& res) {
	//проверяем имя плагина на пустоту
	if (name.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CorePlugin::AddPlugin", QStringList());
		return;
	}

	//запрашиваем список параметров в секции
	QStringList list;
	emit GetParamList("core.ini", "plugins", list);

	//проверяем что такой плагин еще не в списке
	if (list.indexOf(name) >= 0) {
		res=-1;
		emit SetCurrentError(res, "CorePlugin::AddPlugin", QStringList() << name);
		return;
	}

	//добавляем плагин
	list << name;

	//сохраняем обратно
	//удаляем секцию, чтобы не удалять поштучно все параметры
	emit DelSection("core.ini", "plugins");
	//записываем все параметры обратно
	for(int i=0; i<list.count(); i++) {
		emit SetValue("core.ini", "plugins", QString("n%1").arg(i+1), list[i], res);
		if (res > 0) {
			emit SetCurrentError(res, "CorePlugin::AddPlugin", QStringList() << name);
			return;
		}
	}

	res=0;
	emit SetCurrentError(res, "CorePlugin::AddPlugin", QStringList() << name);
}

void CorePlugin::AddPlugin(const QString& name, bool& res) {
	int r;
	AddPlugin(name, r);
	res = (r <= 0);
}

void CorePlugin::AddPlugin(const QString& name) {
	int r;
	AddPlugin(name, r);
}

void CorePlugin::DelPlugin(const QString& name, int& res) {
	//проверяем имя плагина на пустоту
	if (name.isEmpty()) {
		res=1;
		emit SetCurrentError(res, "CorePlugin::DelPlugin", QStringList());
		return;
	}

	//запрашиваем список параметров в секции
	QStringList list;
	emit GetParamList("core.ini", "plugins", list);

	//проверяем что такой плагин уже не в списке
	int p = list.indexOf(name);
	if (p < 0) {
		res=-1;
		emit SetCurrentError(res, "CorePlugin::DelPlugin", QStringList() << name);
		return;
	}

	//удаляем плагин
	list.removeAt(p);

	//сохраняем обратно
	//удаляем секцию, чтобы не удалять поштучно все параметры
	emit DelSection("core.ini", "plugins");
	//записываем все параметры обратно
	for(int i=0; i<list.count(); i++) {
		emit SetValue("core.ini", "plugins", QString("n%1").arg(i+1), list[i], res);
		if (res > 0) {
			emit SetCurrentError(res, "CorePlugin::DelPlugin", QStringList() << name);
			return;
		}
	}

	res=0;
	emit SetCurrentError(res, "CorePlugin::DelPlugin", QStringList() << name);
}

void CorePlugin::DelPlugin(const QString& name, bool& res) {
	int r;
	DelPlugin(name, r);
	res = (r <= 0);
}

void CorePlugin::DelPlugin(const QString& name) {
	int r;
	DelPlugin(name, r);
}

void CorePlugin::AutoList(QStringList& list) {
	//запрашиваем список параметров в секции
	emit GetParamList("core.ini", "plugins", list);
}
